import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import '../internals/enums.dart';
import '../internals/refresh_controller.dart';
import 'classic_footer.dart';
import 'classic_header.dart';

// 定义构建器类型别名
typedef HeaderBuilder = Widget Function(
    BuildContext context, RefreshStatus status);
typedef FooterBuilder = Widget Function(
    BuildContext context, LoadStatus status);

/// 一个功能强大且易于使用的下拉刷新和上拉加载组件。
///
/// 它通过将 Header、Sliver内容、Footer 组合在一个 [CustomScrollView] 中来实现，
/// 从而保证了懒加载列表（如 [SliverList]）的性能。
class FluentRefresher extends StatefulWidget {
  /// 核心控制器，用于手动控制刷新和加载状态，以及监听状态变化。
  final RefreshController controller;

  /// 【高级用法】需要支持刷新和加载的核心滚动内容。
  ///
  /// 这必须是一个 [Sliver] 위젯, 例如 [SliverList] 或 [SliverGrid]。
  /// 这种设计从根本上保证了懒加载的性能。
  /// 对于简单的列表，请考虑使用更方便的 [FluentRefresher.builder] 构造函数。
  final Widget sliver;

  /// 是否启用下拉刷新功能。
  /// 默认为 `true`。
  final bool enablePullDown;

  /// 是否启用上拉加载更多功能。
  /// 默认为 `false`。
  final bool enablePullUp;

  /// 当触发刷新时调用的回调函数。
  /// 你应该在此函数中执行数据获取逻辑，并在完成后调用
  /// [controller.refreshCompleted()] 或 [controller.refreshFailed()]。
  final VoidCallback? onRefresh;

  /// 当触发加载更多时调用的回调函数。
  /// 你应该在此函数中执行数据获取逻辑，并在完成后调用
  /// [controller.loadComplete()], [controller.loadFailed()], 或 [controller.loadNoData()]。
  final VoidCallback? onLoading;

  /// 自定义头部指示器的构建器。
  /// 如果为 null，则使用默认的 [ClassicHeader]。
  final HeaderBuilder? header;

  /// 自定义底部指示器的构建器。
  /// 如果为 null，则使用默认的 [ClassicFooter]。
  final FooterBuilder? footer;

  /// 触发下拉刷新的距离阈值。
  /// 用户向下拖动的距离超过此值后，状态会变为 [RefreshStatus.armed]。
  /// 默认为 60.0。
  final double headerTriggerDistance;

  /// 触发上拉加载的距离阈值。
  /// 当列表滚动到底部，剩余可滚动距离小于此值时，会自动触发 [onLoading] 回调。
  /// 默认为 15.0。
  final double footerTriggerDistance;

  /// 创建一个 `FluentRefresher`。
  ///
  /// 这是高级构造函数，需要你手动传入一个 [sliver] 위젯。
  const FluentRefresher({
    super.key,
    required this.controller,
    required this.sliver,
    this.enablePullDown = true,
    this.enablePullUp = false,
    this.onRefresh,
    this.onLoading,
    this.header,
    this.footer,
    this.headerTriggerDistance = 60.0,
    this.footerTriggerDistance = 15.0,
  });


  /// 创建一个支持刷新和加载的、按需构建子项的列表。
  ///
  /// 这个便捷的构造函数类似于 [ListView.builder]，适用于大多数常见的列表场景。
  /// 它在内部将 [itemBuilder] 和 [itemCount] 转换为一个 [SliverList]，
  /// 并将其传递给默认构造函数，从而保证了最佳性能。
  factory FluentRefresher.builder({
    Key? key,

    /// 核心控制器，用于手动控制刷新和加载状态。
    required RefreshController controller,

    /// 列表项的总数。
    required int itemCount,

    /// 列表项的构建器，类似于 [ListView.builder] 的 `itemBuilder`。
    ///
    /// 它在列表滚动时按需构建子项，接收 `(BuildContext context, int index)`
    /// 两个参数，并返回该索引对应的 Widget。
    required IndexedWidgetBuilder itemBuilder,

    /// 是否启用下拉刷新功能。默认为 `true`。
    bool enablePullDown = true,

    /// 是否启用上拉加载更多功能。默认为 `false`。
    bool enablePullUp = false,

    /// 当触发刷新时调用的回调函数。
    VoidCallback? onRefresh,

    /// 当触发加载更多时调用的回调函数。
    VoidCallback? onLoading,

    /// 自定义头部指示器的构建器。如果为 null，则使用默认的 [ClassicHeader]。
    HeaderBuilder? header,

    /// 自定义底部指示器的构建器。如果为 null，则使用默认的 [ClassicFooter]。
    FooterBuilder? footer,

    /// 触发下拉刷新的距离阈值。默认为 60.0。
    double headerTriggerDistance = 60.0,

    /// 触发上拉加载的距离阈值。默认为 15.0。
    double footerTriggerDistance = 15.0,
  }) {
    return FluentRefresher(
      key: key,
      controller: controller,
      enablePullDown: enablePullDown,
      enablePullUp: enablePullUp,
      onRefresh: onRefresh,
      onLoading: onLoading,
      header: header,
      footer: footer,
      headerTriggerDistance: headerTriggerDistance,
      footerTriggerDistance: footerTriggerDistance,
      sliver: SliverList(
        delegate: SliverChildBuilderDelegate(
          itemBuilder,
          childCount: itemCount,
        ),
      ),
    );
  }

  @override
  State<FluentRefresher> createState() => _FluentRefresherState();
}


class _FluentRefresherState extends State<FluentRefresher> {
// 标记是否可以触发 onRefresh 回调，防止重复调用
  bool _canRefresh = false;

  @override
  void initState() {
    super.initState();
    widget.controller.refreshState.addListener(_onRefreshStateChanged);
    widget.controller.loadState.addListener(_onLoadStateChanged);
  }

  @override
  void dispose() {
    widget.controller.refreshState.removeListener(_onRefreshStateChanged);
    widget.controller.loadState.removeListener(_onLoadStateChanged);
    super.dispose();
  }

  void _onRefreshStateChanged() {
    final status = widget.controller.refreshStatus;
    if (status == RefreshStatus.refreshing && _canRefresh) {
      _canRefresh = false; // 防止重复触发
      widget.onRefresh?.call();
    }
    // 状态变化时，刷新UI
    if (mounted) setState(() {});
  }

  void _onLoadStateChanged() {
    final status = widget.controller.loadStatus;
    if (status == LoadStatus.loading) {
      widget.onLoading?.call();
    }
    if (mounted) setState(() {});
  }

  bool _onScrollNotification(ScrollNotification notification) {
    final metrics = notification.metrics;

    // --- 1. 上拉加载逻辑 (已修正) ---
    // 只有在空闲状态、滚动到底部、并且是滚动更新时才检查
    if (widget.enablePullUp &&
        widget.controller.loadStatus == LoadStatus.idle &&
        metrics.extentAfter < widget.footerTriggerDistance &&
        metrics.pixels > 0) {
      // metrics.pixels > 0 避免在列表内容不足一屏时触发
      // 自动触发加载，无需用户拖拽
      widget.controller.setLoadStatus(LoadStatus.loading);
    }

    // --- 2. 下拉刷新逻辑 (已修正) ---
    if (!widget.enablePullDown) return false;

    // 用户松手时
    if (notification is UserScrollNotification &&
        notification.direction == ScrollDirection.idle) {
      if (widget.controller.refreshStatus == RefreshStatus.armed) {
        _canRefresh = true;
        widget.controller.setRefreshStatus(RefreshStatus.refreshing);
      } else if (widget.controller.refreshStatus == RefreshStatus.pulling) {
        // 如果未达到阈值就松手，则收回
        widget.controller.setRefreshStatus(RefreshStatus.idle);
      }
    }
    // 用户正在拖动时
    else if (notification is ScrollUpdateNotification) {
      // 只有在顶部 (pixels <= 0) 并且是用户拖动时才处理
      if (metrics.pixels <= 0 && notification.dragDetails != null) {
        final status = widget.controller.refreshStatus;
        // 只有在非刷新状态下才更新 pulling/armed
        if (status != RefreshStatus.refreshing &&
            status != RefreshStatus.completed &&
            status != RefreshStatus.failed) {
          if (metrics.pixels.abs() >= widget.headerTriggerDistance) {
            if (status != RefreshStatus.armed) {
              widget.controller.setRefreshStatus(RefreshStatus.armed);
            }
          } else {
            if (status != RefreshStatus.pulling) {
              widget.controller.setRefreshStatus(RefreshStatus.pulling);
            }
          }
        }
      }
    }
    return false;
  }

  @override
  Widget build(BuildContext context) {
    final headerBuilder = widget.header ?? (context, status) => ClassicHeader(status: status);
    final footerBuilder = widget.footer ?? (context, status) => ClassicFooter(status: status, onRetry: () => widget.controller.requestLoading());

    final refreshStatus = widget.controller.refreshStatus;
    final loadStatus = widget.controller.loadStatus;

    // 根据状态判断 Header 是否应该“占据”空间
    final bool isHeaderVisible = refreshStatus != RefreshStatus.idle;
    return NotificationListener<ScrollNotification>(
      onNotification: _onScrollNotification,
      child: CustomScrollView(
        physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
        slivers: [
          // 下拉刷新头部 (Sliver)
          if (widget.enablePullDown)
            SliverToBoxAdapter(
              child: AnimatedContainer(
                duration: const Duration(milliseconds: 200),
                height: isHeaderVisible ? 60.0 : 0,
                alignment: Alignment.center,
                child: isHeaderVisible ? headerBuilder(context, refreshStatus) : null,
              ),
            ),

          // 用户传入的核心内容 (Sliver)
          widget.sliver,

          // 上拉加载底部 (Sliver)
          if (widget.enablePullUp)
            SliverToBoxAdapter(
              // Footer 始终占据空间，由其内部根据状态决定显示内容
              child: footerBuilder(context, loadStatus),
            ),
        ],
      ),
    );
  }
}
